package com.auto.base.config;

import com.auto.base.factory.JdbcTemplate;
import com.auto.base.factory.YamlPropertySourceFactory;
import com.auto.base.params.BaseAutoConfig;
import com.auto.base.util.DubboTemplate;
import com.auto.base.util.MqTemplate;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.*;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.web.client.RestTemplate;
import redis.clients.jedis.JedisPoolConfig;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;


@SuppressWarnings("unused")
@PropertySource(factory = YamlPropertySourceFactory.class, value = "classpath:auto-test-params.yaml")
@Configuration
public class BaseConfig {
    @Bean
    public BaseAutoConfig getParams() {
        return new BaseAutoConfig();
    }
    

    /*jdbcTemplate*/
    @Bean
    JdbcTemplate jdbcTemplate() {
        BaseAutoConfig autoConfigureDto = getParams();
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(autoConfigureDto.getDbDriverClassName());
        dataSource.setUsername(autoConfigureDto.getDbUsername());
        dataSource.setPassword(autoConfigureDto.getDbPassword());
        dataSource.setUrl(autoConfigureDto.getDbUrl());
        return new JdbcTemplate(dataSource);
    }

    /*restTemplate*/
    @Bean
    public HttpClientConnectionManager poolingConnectionManager() {
        PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager();
        poolingConnectionManager.setMaxTotal(1000); // 连接池最大连接数
        poolingConnectionManager.setDefaultMaxPerRoute(500); // 每个主机的并发
        return poolingConnectionManager;
    }


    @Bean
    public HttpClientBuilder httpClientBuilder() {
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        //设置HTTP连接管理器
        httpClientBuilder.setConnectionManager(poolingConnectionManager());
        return httpClientBuilder;
    }

    @Bean("restTemplate")
    public RestTemplate restTemplate() {
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setHttpClient(httpClientBuilder().build());
        httpRequestFactory.setConnectionRequestTimeout(3000);//获取链接超时时间
        httpRequestFactory.setConnectTimeout(3000);//指客户端和服务器建立连接的timeout
        httpRequestFactory.setReadTimeout(120000);//读取数据的超时时间
        return new RestTemplate(httpRequestFactory);
    }

    @Bean
    public DubboTemplate dubboTemplate() {
        BaseAutoConfig autoConfigure = getParams();
        return new DubboTemplate(autoConfigure);
    }

    @Bean("mqTemplate")
    public MqTemplate mqTemplate() {
        BaseAutoConfig autoConfigure = getParams();
        return new MqTemplate(autoConfigure);
    }

    /*redisTemplate*/
    @Bean
    public JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        /*最大连接数*/
        jedisPoolConfig.setMaxTotal(30);
        /*最大空闲时间*/
        jedisPoolConfig.setMaxIdle(10);
        /*每次最大连接数*/
        jedisPoolConfig.setNumTestsPerEvictionRun(1024);
        /*#释放扫描的扫描间隔*/
        jedisPoolConfig.setTimeBetweenEvictionRunsMillis(30000);
        /*#连接的最小空闲时间*/
        jedisPoolConfig.setMinEvictableIdleTimeMillis(1800000);
        /*连接控歘按时间多久后释放，当空闲时间>该值且空闲连接>最大空闲连接数时直接释放*/
        jedisPoolConfig.setSoftMinEvictableIdleTimeMillis(10000);
        /*获得链接时的最大等待毫秒数，小于0：阻塞不确定时间，默认-1*/
        jedisPoolConfig.setMaxWaitMillis(1500);
        /*在获得链接的时候检查有效性，默认false*/
        jedisPoolConfig.setTestOnBorrow(true);
        /*在空闲时检查有效性，默认false*/
        jedisPoolConfig.setTestWhileIdle(true);
        /*连接耗尽时是否阻塞，false报异常，true阻塞超时,默认true*/
        jedisPoolConfig.setBlockWhenExhausted(false);
        return jedisPoolConfig;
    }

    /*
    *  BaseAutoConfigDto autoConfigureDto = getParams();
            if (autoConfigureDto.getCacheType().equals("ctgcache")){
                return null;
            }
    * */
    @Bean
    RedisClusterConfiguration redisClusterConfiguration() {
        BaseAutoConfig autoConfigureDto = getParams();
        List<RedisNode> redisNodes = new ArrayList<>();
        for (String cacheServerList : autoConfigureDto.getCacheServerList().split(",")) {
            RedisNode redisNode = new RedisNode(cacheServerList.split(":")[0], Integer.parseInt(cacheServerList.split(":")[1]));
            redisNodes.add(redisNode);
        }
        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
        redisClusterConfiguration.setMaxRedirects(5);
        redisClusterConfiguration.setClusterNodes(redisNodes);
        return redisClusterConfiguration;
    }

    @Resource
    JedisPoolConfig jedisPoolConfig;

    @Resource
    RedisClusterConfiguration redisClusterConfiguration;

    @Resource
    BaseAutoConfig baseAutoConfigDto;

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        if (baseAutoConfigDto.getCacheType().equals("redis")) {
            return new JedisConnectionFactory(redisClusterConfiguration, jedisPoolConfig);
        }
        return new RedisConnectionFactory() {
            @Override
            public DataAccessException translateExceptionIfPossible(RuntimeException e) {
                return null;
            }

            @Override
            public RedisConnection getConnection() {
                return null;
            }

            @Override
            public RedisClusterConnection getClusterConnection() {
                return null;
            }

            @Override
            public boolean getConvertPipelineAndTxResults() {
                return false;
            }

            @Override
            public RedisSentinelConnection getSentinelConnection() {
                return null;
            }
        };
    }

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
    }
}
